package com.cn.component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

 













import com.cn.constant.ProConstant;
import com.cn.controller.OrderController;
import com.cn.domain.OrderEntity;
import com.cn.domain.ProductEntity;
import com.cn.service.DistributedLocker;
import com.cn.service.OrderService;
import com.cn.service.ProductService;
import com.cn.service.RedisLockService;
 

@Component
@Order(3)
public class BackUpExcutors {
	
	private Logger  logger = LoggerFactory.getLogger(this.getClass());
	@Autowired  
    private RedisTemplate redisTemplate;
	
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
    @Autowired
	private DistributedLocker distributedLocker;
    
	@Autowired
	private ProductService productService;
	
	@Autowired
	private OrderService orderService;
	@Autowired
	private RedisLockService redisLockService;
	
	  
	
	
	private ExecutorService executorService;
	
    private List<ProductJob> listJob;
	private int num=100; 
    @PostConstruct // 在构造函数执行完之后执行
    public void init(){
    	
    	System.out.println("init");
        executorService = Executors.newFixedThreadPool(num);
        //获取所有商品信息，遍历商品的所有队列
        ProductEntity product = new ProductEntity();
        List<ProductEntity> result = this.productService.
        		         findProductEntityByWhere(product);
         
        for(int i=0;i<result.size();i++){
        
        	
        	 this.redisTemplate.opsForValue().getOperations().delete("lock"+result.get(i).getProductId());
        	 this.redisTemplate.opsForValue().getOperations().delete("productNum"+result.get(i).getProductId());
        	 this.redisTemplate.opsForValue().set("ProductNum", result.get(i).getProductNum());
        	 
        	ProductJob pjob =new ProductJob(orderService,redisTemplate,result.get(i),distributedLocker,stringRedisTemplate);
        	  executorService.submit(pjob);
            System.out.println(" executorService start");
        }
    }

    public BackUpExcutors() {
        super();

        
        
    }

    @PreDestroy // 在Bean销毁之前执行
    private void destroy(){
        System.out.println("BackUpExcutors end");
        for(int i=0;this.listJob!=null&&i<this.listJob.size();i++){
        	this.listJob.get(i).stopJob();
        }
       
        if(!this.executorService.isShutdown()){
        	this.executorService.shutdown();
        	System.out.println("executorService end");
        }
    }
}
class ProductJob implements  Callable<Integer>{
    private OrderService orderService;
    
    private RedisTemplate redisTemplate;
    
    private StringRedisTemplate stringRedisTemplate;
    
	private ProductEntity productEntity;
	
	private DistributedLocker distributedLocker;
	private boolean stop;
	 Logger logger = (Logger) LoggerFactory.getLogger(ProductJob.class);
	public ProductJob(OrderService orderService,RedisTemplate redisTemplate,
			      ProductEntity productEntity,DistributedLocker distributedLocker,
			      StringRedisTemplate stringRedisTemplate){
		this.orderService=orderService;
		this.redisTemplate=redisTemplate;
		this.productEntity=productEntity;
		this.distributedLocker = distributedLocker;
		this.stringRedisTemplate = stringRedisTemplate;
		this.stop=false;
	}
	
	String lock = ProConstant.LOCK;
	String queue = ProConstant.QUEUE;
	
	public Integer call() throws Exception {
		// TODO Auto-generated method stub
		while(!stop){
			Long productId= productEntity.getProductId();
           	String lockQueue=lock+productId;
           	RLock rlock=distributedLocker.lock(lockQueue);
           	rlock.lock();
            if(rlock.isLocked()){
            	
            	try{
            		 
	            	//取出相应队列中的pro信息进行消费
            	
            		
	            	String queueInfo=queue+productId;
	            	comsumerOther("JsonList"+productId,stringRedisTemplate);
	            	
	            	long length =redisTemplate.opsForList().size(queueInfo);
	            	if(length >1200){
	            		length =1200;
	            	}
	            	List<OrderEntity> orderList =  redisTemplate.opsForList()
	            			.range(queueInfo, 0, length);
	            	
	            	if(orderList!=null&&orderList.size() >0){
	            		
	            		 System.out.println("insert "+lockQueue);
		            	int ex = orderService.insertBatchOrder(orderList);
		            	if(0>=ex){
		            		System.out.println("Error in batch insert");
		            		throw new Exception(" error batch insert");
		            	}
		            	for(long i=0;i<orderList.size() ;i++){
		            		 redisTemplate.opsForList().leftPop(queueInfo);
		            		 
		            	}
	            	}
	            	
	            	
            	}catch(Exception e){
            		e.printStackTrace();
            		
            	}finally{
            		distributedLocker.unlock(lockQueue); 
            		
            	}
            	
            }
           
           
		}
		return 1;
	}
	
	public void stopJob(){
		this.stop=true;
	}
	
	public int comsumerOther(String queueName,StringRedisTemplate stringTemplate){
		
		//取出相应队列中的pro信息进行消费
    	String queueInfo=queueName;
     
    	List<OrderEntity> orderList = new ArrayList<OrderEntity>();
    	SnowFlake snowFlake=new SnowFlake(0,0);
    	long length =stringTemplate.opsForList().size(queueInfo);
    	if(length >1200){
    		length =1200;
    	}
    	 List<String> list =  stringTemplate.opsForList()
    			.range(queueInfo, 0, length);
    	 if(list!=null&&list.size() >0){
    		 for(int x =0 ;x<list.size(); x++){
    			 String[] info= list.get(x).split("_");
    			 OrderEntity order = new OrderEntity();
	   		      order.setModifyTime(new Date());
	   		      order.setProductId(Long.parseLong(info[0]));
	   		      order.setNum(Integer.parseInt(info[1]));
	   		      order.setUserId(Long.parseLong(info[2]));
	   		      order.setOrderNo(snowFlake.nextId()+"");
	   	      	  orderList.add(order);
    		 }
    		 
    	 }
     
    	if(orderList.size() > 0){
    	   int ex = orderService.insertBatchOrder(orderList);
    	   if( ex <= 0){
    		   return 0;
    	   }
    	}
    	
    	for(long i=0;i<list.size() ;i++){
   		   this.stringRedisTemplate.opsForList().leftPop(queueInfo);
   		 
      	}   
     
    	 
    	return 1;
	}
	
}
